#!/usr/bin/env python
#-*-coding:utf-8-*-

'''
Created on May 20, 2010
@author: flor
'''
import optparse
import platform

################################################################################
# META
################################################################################

__prj__ = "hostsupdate"
__version__ = "1.0"
__author__ = "Flor"
__since__ = "0.1"
__date__ = "2010"
__license__ = "gpl3"
__copyright__ = """%s %s Copyright (C) %s %s
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions; for details see LICENSE.txt.""" % (__prj__,
                                                            __version__,
                                                            __date__,
                                                             __author__)

class OhMyGodIsDoubleIndexedDictionary(object):
    
    def __init__(self):
        self._host_as_key = {}
        self._ip_as_key = {}
        
    def __eq__(self, obj):
        if isinstance(obj, self.__class__):
            return self._host_as_key == obj._host_as_key and self._ip_as_key == obj._ip_as_key
        
    def __neq__(self, obj):
        return not (self == obj)
        
    def add_value(self, k, v, ip=True):
        if ip:
            self._ip_as_key[k] = v
            self._host_as_key[v] = k
        else:
            self._ip_as_key[v] = k
            self._host_as_key[k] = v
                    
    def get_value(self, k, ip=True):
        
        if ip:
            host = self._ip_as_key[k]
            ip = self._host_as_key[host]
            if ip == k:
                return host
            else:
                print("error, no consistencia")
        else:
            ip = self._host_as_key[k]
            host = self._ip_as_key[ip]
            if host == k:
                return ip
            else:
                print("error, no consistencia")
        
        #return self._ip_as_key[k] if ip else self._host_as_key[k]
        
    def consistency_check(self):
        
        for ip, host in self._ip_as_key.items():
            ipn = self._host_as_key[host]
            if not ipn == ip:
                print("error, same host=%s for %s and %s" % (host, ip, ipn))
            
        for host, ip in self._host_as_key.items():
            hostn = self._ip_as_key[ip]
            if not hostn == host:
                print("error, same ip=%s for %s and %s" % (ip, host, hostn))
    
class HostError(object):
    
    def __init__(self, msg, code):
        self.msg = msg
        self.code = code
        super(HostError, self).__init__()

    def __str__(self):
        # cuando se hace 'str(instancia)' se llama a este metodo
        return self.msg


class HostsUpdate(object):

    def __init__(self, path):
        """Crea una nueva instancia de HostsUpdate

        @param file: index_hosts file

        """
        self.path = path
        self.file = open(path)
        self.index_hosts = OhMyGodIsDoubleIndexedDictionary()
        self.hosts = {}
        it = iter(self.file)
        
        for i in it:
            aux = self._clean_string(i)
            if aux:
                self.index_hosts.add_value(aux[0], aux[1], ip=True)
        
        super(HostsUpdate, self).__init__()

    def __str__(self):
        # cuando se hace 'str(instancia)' se llama a este metodo
        return self.index_hosts



    def _clean_string(self, line):
        ''' cleans one line strings to get the ip and hostname'''
        
        line = line.strip().lower()
        comment = line.split('#')
        # line is what is not commented
        line = comment.pop(0)
        # mark comments with # later they will be added to list
        if comment:
            for i in range(0, len(comment) - 1):
                comment[i] = "#" + comment[i]
        line = line.replace(' ', '\t')
        hostalias = []
        if line:
            lsalias = line.split('\t')
            for i in lsalias:
                if i:
                    hostalias.append(i)
            ip = hostalias.pop(0)
#            if ip.count('.') == 3:
#                #is ok, regular ip
#                pass
            if ip.count(':') == 2 or ip == "127.0.0.1":
                comment.insert(0, "#DNT")
                
#            if len(hostalias) != 1:
#                for i in hostalias:
#                    if not i.count('.'):
#                        host = i
#            else:
#                host = hostalias[0]
            return ip, hostalias + comment


    def _append_file(self, path):
        f = open(path)
        
        it = iter(f)
        
        for i in it:    def _excluded(self, string):
        
        osname = platform.node()
        
        excluded = [osname, "127.0.0.1", "localhost"]
        if excluded.__contains__(string):
            return True
        elif string.find(":") != -1:
            return True
        else:
            return False
            try:
                k, v = self._clean_string(i)
                if k and v:
                    try:
                        host = self.index_hosts.get_value(k, True)
                        ip = self.index_hosts.get_value(v, False)
                    except KeyError:
                        self.index_hosts.add_value(k, v)
            except TypeError:
                pass
            
#                if host and ip: 
#                    if pair[0] != ip or pair[1] != host:
#                        # el host y el ip existen pero estan cruzados?
#                        msg = "Conflict: ip and host are present, but with different" \
#                                "values: k=%s v=%s ip=%s host=%s"
#                        raise HostError (msg % (ip, host, pair[0], pair[1]), 1)
#                elif host or ip:
#                    # 1 de los 2 no existe, y 1 de los 2 si
#                    if host: # existe el host, con otra ip
#                        msg = "Conflict: hosts exists with a different ip: k=%s v=%s ip=%s host=%s"
#                        raise HostError (msg % (ip, host, pair[0], pair[1]), 2)
#                    else: # existe el ip y el host no
#                        msg = "Conflict: ip exists assigned to another host: k=%s v=%s ip=%s host=%s"
#                        raise HostError (msg % (ip, host, pair[0], pair[1]), 2)
            
            #else:
             #   print("none pair %s" % pair)
              #  msg = "pair variable None -->" + pair
               # raise HostError(msg, 3)

    
    def _check_hosts_file(self, path):
        f = open(path)
        d = {}
        while f:
            aux = f.next().split("\t", 1)
            try:
                aux[0].index('#')
            except ValueError:
                d[aux[0]] = aux[1]
        return d
            


    
    def _update(self, pair):
        if pair:
            host = self.index_hosts.get_value(pair[0], True)
            ip = self.index_hosts.get_value(pair[1], False)
                    
            if host and ip: 
                if pair[0] != ip or pair[1] != host:
                    # el host y el ip existen pero estan cruzados?
                    msg = "Conflict: ip and host are present, but with different" \
                          "values: k=%s v=%s ip=%s host=%s"
                    raise HostError (msg % (ip, host, pair[0], pair[1]), 1)
                elif host or ip:
                    # 1 de los 2 no existe, y 1 de los 2 si
                    if host: # existe el host, con otra ip
                        msg = "Conflict: index_hosts exists with a different ip: k=%s v=%s ip=%s host=%s"
                        raise HostError (msg % (ip, host, pair[0], pair[1]), 2)
                    else: # existe el ip y el host no
                        msg = "Conflict: ip exists assigned to another host: k=%s v=%s ip=%s host=%s"
                        raise HostError (msg % (ip, host, pair[0], pair[1]), 2)
                else:
                    #ninguno de los 2 existe --> lo agrego
                    self.index_hosts.add_value(pair[0], pair[1])
            else:
                msg = "pair variable None -->" + pair
                raise HostError(msg, 3)
    
    def _find_host(self, key):
        pass




if __name__ == '__main__':
    ''' por defecto puede buscar el host o chequear el archivo por errores '''
    
    parser = optparse.OptionParser("usage: %s [option] [HOST] \n"
                                        "\t[HOST] to look for in the default file\n"
                                        "%s\n%s" % (__prj__, __doc__, __copyright__),
                                        version=__version__)
    parser.add_option("-f", "--file", action="store", type="string",
                       dest="file",
                       help="file to append",
                       metavar="FILE")
    parser.add_option("-u", "--update", action="store", type="string",
                       dest="host",
                       nargs=2,
                       help="add or change host's ip",
                       metavar="HOST IP")
    parser.add_option("-r", "--remove", action="store", type="string",
                       dest="remove",
                       help="remove host",
                       metavar="HOST")
    parser.add_option("-i", "--ip", action="store", type="string",
                       dest="ip",
                       help="search by ip",
                       metavar="IP")
    
    options, args = parser.parse_args()
    h = HostsUpdate("/home/flor/tests/hosts1112")
    
